package com.gzhryc.shared_device.oem.micro.iot;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.pay.adaptation.weixin.WXPayAdvancePayService;
import com.gzhryc.pay.adaptation.weixin.WXPayNormalPayService;
import com.gzhryc.pay.adaptation.weixin.enums.EWXPayNormalRefundState;
import com.gzhryc.pay.adaptation.weixin.msg.advance_pay.WXPayAdvancePayFinishResponse;
import com.gzhryc.pay.adaptation.weixin.msg.normal.WXPayNormalRefundResponse;
import com.gzhryc.pay.enums.TradeType;
import com.gzhryc.pay.models.RevertBillParam;
import com.gzhryc.shared_device.base.enums.ELogState;
import com.gzhryc.shared_device.base.enums.EOrderOperateState;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.cdb.code.ICDBBusinessEventListener;
import com.gzhryc.shared_device.cdb.code.dao.db.BatteryCabinet;
import com.gzhryc.shared_device.cdb.code.dao.db.CDBOrder;
import com.gzhryc.shared_device.cdb.code.dao.db.PortableBattery;
import com.gzhryc.shared_device.cdb.code.dao.enums.CDBOrderEnum;
import com.gzhryc.shared_device.cdb.code.dao.enums.ECDBCostMode;
import com.gzhryc.shared_device.cdb.code.services.BatteryCabinetService;
import com.gzhryc.shared_device.cdb.code.services.CDBOrderLogService;
import com.gzhryc.shared_device.cdb.code.services.CDBOrderService;
import com.gzhryc.shared_device.cdb.core.models.CDBLeaseResult;
import com.gzhryc.shared_device.cdb.core.models.CDBReturnNotify;
import com.gzhryc.shared_device.common.device.dao.db.Device;
import com.gzhryc.shared_device.common.device.dao.db.DeviceType;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.common.device.services.DeviceTypeService;
import com.gzhryc.shared_device.common.payment.dao.db.WXPayOrder;
import com.gzhryc.shared_device.common.payment.dao.db.WXRefundOrder;
import com.gzhryc.shared_device.common.payment.services.WXPayOrderService;
import com.gzhryc.shared_device.common.payment.services.WXRefundOrderService;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.PayServiceFactory;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.order.RedisCacheManager;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlacePhysicalStore;
import com.gzhryc.shared_device.oem.code.place.services.PlacePhysicalStoreService;

import java.util.Date;

public class CDBBusinessEventListener implements ICDBBusinessEventListener {

    static Logger log = Logger.getLogger(CDBBusinessEventListener.class);

    @Override
    public void leaseResult(CDBOrder deviceOrder, CDBLeaseResult leaseResult) {

    }

    @Override
    public void revertResult(CDBOrder deviceOrder, PortableBattery portableBattery, CDBReturnNotify returnNotify, OperateInfo operateInfo) {
        BatteryCabinet batteryCabinet = BatteryCabinetService.self().getByDeviceSn(returnNotify.getDeviceSn());
        if (batteryCabinet == null) {
            log.error("未找到归还的机柜，归还信息：{{0}}", returnNotify);
            return;
        }
        Date endDate = new Date();
        Long useDuration = DateTools.differenceSecond(deviceOrder.getStartDate(), endDate);
        Long freeTimes = deviceOrder.getFreeTimes() * 60L;       //分钟变秒
        deviceOrder.setRevertChargingCabinetSn(returnNotify.getDeviceSn());
        deviceOrder.setRevertPower(returnNotify.getPower());
        deviceOrder.setRevertSlotNum(returnNotify.getSlotNum());
        deviceOrder.setEndDate(endDate);
        deviceOrder.setUseDuration(useDuration);

        Integer money = 0;
        Integer refundMoney = 0;
        Long times = useDuration;
        if (useDuration >= 86400) {
            Long dayCount = useDuration / 86400;
            times = useDuration % 86400;
            money = dayCount.intValue() * deviceOrder.getDayMaxMoney();
        }

        if (times > freeTimes) {
            if(times >= 3600) {
                //计算金额
                Long hour = times / 3600;
                money = deviceOrder.getPayIntervalMoney() * hour.intValue();
                times = times % 3600;
            }

            if(times > freeTimes) {
                Integer tempMoney = 0;
                if (times > 1800 + freeTimes) {
                    tempMoney = deviceOrder.getPayIntervalMoney();
                } else {
                    tempMoney = deviceOrder.getPayIntervalMoney() / 2;
                }
                money = money + tempMoney;
            }

            if (money > deviceOrder.getDayMaxMoney()) {
                money = deviceOrder.getDayMaxMoney();
            }
        }

        if (money >= deviceOrder.getDepositMoney()) {
            money = deviceOrder.getDepositMoney();
        } else {
            refundMoney = deviceOrder.getDepositMoney() - money;
        }

        Double payMoney = NumberTools.changeMoney(money);

        deviceOrder.setMoney(NumberTools.changeMoneyLi(payMoney));
        deviceOrder.setPayMoney(money.intValue());

        if(ECDBCostMode.ExemptionDeposit.index().equals(deviceOrder.getCostMode())) {
        	deviceOrder.setPayState(CDBOrderEnum.PayState.AdvancePaying.index());
        }else {
	        if (refundMoney > 0) {
	            deviceOrder.setPayState(CDBOrderEnum.PayState.DepositRefund.index());
	        } else {
	            deviceOrder.setPayState(CDBOrderEnum.PayState.PaySuccess.index());
	        }
        }

        Device device = DeviceService.self().getByDeviceSn(batteryCabinet.getDeviceSn());
        if (device != null) {
            deviceOrder.setRevertDeviceTypeId(device.getDeviceTypeId());
            deviceOrder.setRevertDeviceTypeName(device.getDeviceTypeName());
            deviceOrder.setRevertBindNote(device.getBindNote());
            if (device.getPlaceId() != null) {
                deviceOrder.setRevertPlaceId(device.getPlaceId());
                deviceOrder.setRevertPlaceName(device.getPlaceName());
                deviceOrder.setRevertProvince(device.getProvince());
                deviceOrder.setRevertCity(device.getCity());
                deviceOrder.setRevertCityArea(device.getCityArea());
                deviceOrder.setRevertAreaCode(device.getAreaCode());

                PlacePhysicalStore physicalStore = PlacePhysicalStoreService.self().getById(device.getPlaceId());
                if(physicalStore != null){
                    deviceOrder.setRevertAddress(physicalStore.getAddress());
                    deviceOrder.setRevertAgentId(physicalStore.getUserId());
                    deviceOrder.setRevertLongitude(physicalStore.getLongitude());
                    deviceOrder.setRevertLatitude(physicalStore.getLatitude());
                }
            }
        } else if (batteryCabinet.getDeviceTypeId() != null) {
            DeviceType deviceType = DeviceTypeService.self().getById(batteryCabinet.getDeviceTypeId());
            deviceOrder.setRevertDeviceTypeId(deviceType.getId());
            deviceOrder.setRevertDeviceTypeName(deviceType.getName());
        }

        operateInfo.setOperateNote("充电宝归还成功，总费用" + deviceOrder.getMoneyStr() + "元");
        if (CDBOrderService.self(deviceOrder.getCreateDate()).revertFinish(deviceOrder, operateInfo)) {
            //清理缓存，避免定时器重复处理
            RedisCacheManager.removeWorkingCDBDeviceOrder(deviceOrder.getTradeNo());
            Integer operateState = ELogState.Success.index();
            String errorMsg = null;
            try {
                if (CDBOrderService.self(deviceOrder.getCreateDate()).noOperateTo(deviceOrder.getTradeNo(), EOrderOperateState.Finishing.index())) {
                    WXPayOrder payOrder = WXPayOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getPayTradeNo());
                    if(TradeType.PreAuthPay.name().equals(payOrder.getTradeType())) {
                    	WXPayAdvancePayService payService = PayServiceFactory.self().getWXPayAdvancePayService(payOrder.getAppId(), payOrder.getBusinessType());
                    	RevertBillParam param = CDBOrderService.buildRevertBillParam(deviceOrder);
                    	payService.applyFinishOrder(payOrder, param);
                    	WXPayAdvancePayFinishResponse finishResponse = payService.applyFinishOrder(payOrder, param);
        				if (finishResponse != null) {
        					log.info("{{0}}订单完成时，微信支付分完成响应：{{1:json}}",deviceOrder.getTradeNo(),finishResponse);
        					
        					//记录日志
	                        operateInfo.setOperateNote("免押支付费用：" + NumberTools.getMoneyStr(payMoney) + "元");
	                        CDBOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
        					
        					/*if(EWXPayAdvanceServerState.DONE.name().equals(finishResponse.getState()) ||
        							EWXPayAdvanceServerState.DOING.name().equals(finishResponse.getState())){
        					}*/
        				}else {
        					log.info("{{0}}订单完成时，微信支付分完成无响应",deviceOrder.getTradeNo());
        				}
                    }else {
                    	if(refundMoney > 0) {
	                        WXPayNormalPayService payService = PayServiceFactory.self().getWXPayNormalPayService(payOrder.getAppId(), payOrder.getBusinessType());
	                        WXRefundOrder refundOrder = WXRefundOrderService.self(deviceOrder.getCreateDate()).createRefundOrder(payOrder, refundMoney, operateInfo.getOperateNote());
	                        WXPayNormalRefundResponse externalResult = payService.applyRefundOrder(refundOrder);
	                        if (externalResult != null) {
	                            if (EWXPayNormalRefundState.SUCCESS.name().equals(externalResult.getStatus())) {
	                                int result = CDBOrderService.self(new Date()).refundSuccess(refundOrder, operateInfo);
	                                if (result == 3) {
	                                    deviceOrder = CDBOrderService.self(refundOrder.getCreateDate()).getByTradeNo(refundOrder.getBusinessTradeNo());
	                                    MemberBusinessOrderService.self(refundOrder.getCreateDate()).finish(refundOrder.getBusinessTradeNo(), deviceOrder.getMoney()
	                                            , deviceOrder.getPayMoney(), deviceOrder.getWalletMoney());
	                                } else {
	                                    log.error("{{0}}订单微信退款成功，但处理订单返回值非预期3，返回为：{{1}}", payOrder.getTradeNo(), result);
	                                }
	                            } else if (!EWXPayNormalRefundState.PROCESSING.name().equals(externalResult.getStatus())) {
	                                if (StringTools.isNotBlank(externalResult.getCode())) {
	                                    errorMsg = externalResult.getMessage();
	                                } else {
	                                    if (EWXPayNormalRefundState.CLOSED.name().equals(externalResult.getStatus())) {
	                                        errorMsg = "退款已关闭";
	                                    } else {
	                                        errorMsg = "退款异常";
	                                    }
	                                }
	                                operateState = ELogState.Fail.index();
	                                WXRefundOrderService.self(deviceOrder.getCreateDate()).toFail(payOrder.getTradeNo(), errorMsg, JsonTools.toJson(externalResult));
	                            }
	                        } else {
	                            operateState = ELogState.Fail.index();
	                            errorMsg = "微信退款失败，无响应";
	                            log.error("{{0}}订单微信退款失败，无返回信息", payOrder.getTradeNo());
	                        }
	                        
	                        //记录日志
	                        operateInfo.setOperateNote("押金支付后退款：" + NumberTools.getMoneyStr(refundMoney) + "元");
	                        CDBOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
                    	}else{
                            //同步会员订单
                            deviceOrder = CDBOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
                            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(),deviceOrder.getMoney(),deviceOrder.getPayMoney()
                                    ,deviceOrder.getWalletMoney());

                            //触发订单完成
                            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
                            if (producer != null) {
                                OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.CDB.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), temp);
                                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                                producer.send(kafkaMessage);
                            }else{
                                log.error("未初始化消息队列，订单{{0}}未触发完成事件",deviceOrder.getTradeNo());
                            }
                        }
                    }
                }else{
                    operateState = ELogState.Fail.index();
                    errorMsg = "微信退款时锁定订单失败";
                    log.error("{{0}}订单微信退款时锁定订单失败", deviceOrder.getTradeNo());
                }
            } catch (LogicException e) {
                log.error(e.getMessage(), e);
            }
        } else {
            log.error("归还充电宝处理失败，订单：{{0:json}}", deviceOrder);
        }
    }
}
